/* (C) C.D.F. Miller, Heriot-Watt University, March 1984
 *
 *	Permission is hereby given to reproduce or modify this
 *	software freely, provided that this notice be retained,
 *	and that no use be made of the software for commercial
 *	purposes without the express written permission of the
 *	author.
 */

#include	<lbl.h>
#include	<ctype.h>
#include        <string.h>
#include        <err.h>
#include        "build.h"
#include        "scan.h"
#include	"keyword.h"

void	process(char *);
us int	split(char *line, char *argvec[]);

extern char macroname[];
extern char *filename;
extern int sflag;
extern FILE *tempfile;
extern long fileline;

void
scan(char *fname, FILE *f)
{
	char line[BUFSIZ];
	int line_complete = 1;

	/*
	 * Mark start of file in temp file
	 */
	if (!sflag)
		fprintf(tempfile, "%c%c%c%s\n", MAGIC1, MAGIC2, M_FILE, fname);
	filename = fname;
	fileline = 0L;

	while (fgets(line, BUFSIZ, f) != NULL) {
		if (!sflag)
			fputs(line, tempfile);
		if (line_complete) {
			fileline++;
			line_complete = line[strlen(line) - 1] == '\n';
			if (line[0] == '.' && line[1] == macroname[0] &&
			          line[2] == macroname[1]) {
				if (line_complete)
					process(line + 3);
				else
					warnx("%s.%s line too long",
					      maybe_loc(), macroname);
			}
		}
		else
			line_complete = line[strlen(line) - 1] == '\n';
	}
}

void
process(char *line)
{
	us int nargs;
	char *argvec[NLEVELS + 2];
	Keyword *key;

	if ((nargs = split(line, argvec)) == 0) {
		warnx("%sempty .%s line", maybe_loc(), macroname);
		return;
	}
	/*
	 * Check for and act upon reserved words
	 */
	if ((key = findkeyword(argvec[0])) != NULL) {
		if (nargs < key->k_minargs) {
			warnx("%s%s - too few arguments", maybe_loc(),
			      key->k_name);
			return;
		}
		if (nargs > key->k_maxargs) {
			warnx("%s%s - too many arguments", maybe_loc(),
			      key->k_name);
			return;
		}
		(*(key->k_action)) (nargs, argvec);
		return;
	}
	/*
	 * Process a label definition
	 */
	if (nargs != 3) {
		warnx("%stoo %s arguments in label definition",
		      maybe_loc(), nargs < 3 ? "few" : "many");
		return;
	}
	addlbl(argvec[0], argvec[1], argvec[2]);
}

/* split - split a line into arguments
 *	N.B. successive calls of this invalidate earlier calls;
 *	argvec is set to point to strings within the
 *	static local buffer "copybuf" which is overwritten on
 *	each call.
 */
us int
split(char *line, char *argvec[])
{
	us int nargs = 0;
	static char copybuf[BUFSIZ];
	char *ln = copybuf;

	strlcpy(ln, line, BUFSIZ);
	while (*ln) {
		while (isspace(*ln))
			ln++;
		if (*ln) {
			if (nargs > 2 + NLEVELS) {
				warnx("%ssurplus arguments to .%s ignored",
				      maybe_loc(), macroname);
				break;
			}
			argvec[nargs++] = ln;
			while (*ln && !isspace(*ln))
				ln++;
			if (*ln)
				*ln++ = '\0';
		}
	}
	if (nargs > 2 + NLEVELS)
		nargs = 2 + NLEVELS;
	return nargs;
}
